#ifndef HASHTABLE_H
#define HASHTABLE_H

#include <QString>
#include <QRegExp>
#include <QVector>

class Par {
public:
    char key[5];
    qint64 value;

    Par() : value(0) {
        key[0] = 0;
    }

    Par(QString k, qint64 v) {
        for (int i = 0; i < 4; i++)
            if (k.length() >= i) this->key[i] = k.toAscii().data()[i];
            else this->key[i] = 0;
        this->key[4] = 0;
        this->value = v;
    }
};

class HashTabulka {
protected:
    QVector<Par> data[703];

    unsigned int hash(QString s) {
        unsigned int ret = 1;
        for (char i = 0; i < 2; i++) {
            char c = s[i].toLower().toAscii();
            if (c >= 'a' && c <= 'z') {
                ret += (c - 'a' + 1) * ((i > 0) ? 1 : 26);
            }
        }
        return ret;
    }

public:
    void pridej(QString s, qint64 v) {
        s.truncate(4);
        data[this->hash(s)].push_back(Par(s, v));
    }

    QVector<qint64> najdi(QString s) {
        QVector<qint64> ret;
        s.truncate(4);
        QRegExp regexp("^" + s.toAscii());
        foreach(Par p,this->data[this->hash(s)]) {
            if (QString(p.key).contains(regexp)) {
                ret.push_back(p.value);
            }
        }
        return ret;
    }

    struct souborovyFormat {
        unsigned int index;
        qint64 pos;
        char key[5];
        souborovyFormat(unsigned int index, qint64 pos, char * key) {
            this->index = index;
            this->pos = pos;
            for (int i = 0; i < 5; i++) this->key[i] = key[i];
        }

        souborovyFormat() {
        }
    };

    void uloz(QString filename) {
        QFile output(filename);
        if (output.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
            for (int i = 0; i < 703; ++i) {
                foreach(Par p,this->data[i]) {
                    souborovyFormat zaznam(i,p.value,p.key);
                    output.write((char *) & zaznam, sizeof (souborovyFormat));
                }
            }
        }
    }

    void nacti(QString filename) {
        QFile input(filename);
        if (input.open(QIODevice::ReadOnly)) {
            souborovyFormat *zaznam = new souborovyFormat;
            while (!input.atEnd()) {
                input.read((char*) zaznam, sizeof (souborovyFormat));
                this->data[zaznam->index].push_back(Par(zaznam->key, zaznam->pos));
            }
            delete zaznam;
            for (int i = 0; i < 703; ++i) {
                this->data[i].squeeze();
            }
        }
    }
};
#endif // HASHTABLE_H
